home *** CD-ROM | disk | FTP | other *** search
- ; rootsect.s
-
- ;------------------------------------------------------------------------
- ; :
- ; Hard Disk Root Sector :
- ; Initiates boot from a hard disk partition, contains hard disk :
- ; read-sector subroutine for use by partition's boot code. :
- ; :
- ; Copyright 1986, 1987, 1988, 1989, 1990 Atari Corp. :
- ; All Rights Reserved :
- ; :
- ; Jul-24-1989 ml. Modified this for TT. :
- ; New ROMs will pass the following to this :
- ; root sector: :
- ; d3.l = $444d4172 ("DMAr") to indicate the XBIOS :
- ; call for DMAread exists. :
- ; d4.w = boot unit # (iff d3.l = "DMAr") :
- ; d5.w = user-preference (ignore for now!!) :
- ; d7.b = ACSI device # in upper 3 bits :
- ; (should ignore d7.b if d4.w is valid) :
- ; Feb-05-1990 ml. Modified to reflect the latest boot spec. which :
- ; includes booting UNIX on the TT. :
- ; Removed code that handles MSDOS root sector. :
- ; Handled user-preference as stated in latest :
- ; TT boot spec. :
- ; Feb-14-1990 ml. If a user-preference is passed in through d5 :
- ; but no entry matches it, just quit. Maybe the :
- ; preference is for another kind of device. :
- ; Jul-25-1990 ml. Modified handling of user-preference code, so :
- ; that bits 1 & 2 of byte 0 of a partition entry :
- ; do not participate in the comparison. (This :
- ; lifts the assumption that they have to be 0.) :
- ; :
- ;------------------------------------------------------------------------
-
-
- ;---- Hardware registers:
- diskctl equ $ffff8604 ; (W) disk controller data access
- fifo equ $ffff8606 ; (W) DMA mode control
- dmahigh equ $ffff8609 ; (B) DMA base high
- dmamid equ $ffff860b ; (B) DMA base medium
- dmalow equ $ffff860d ; (B) DMA base low
- gpip equ $fffffa01 ; (B) bit 5 is DMA interrupt line
-
- ;---- OS locations:
- flock equ $43e ; (W) DMA chip lock variable
- _bootdev equ $446 ; (W) boot device number
- _hz_200 equ $4ba ; (L) 200 hz timer tick
- _drvbits equ $4c2 ; (L) logical drive map
- _dskbufp equ $4c6 ; (L) -> 1K disk buffer
- _sysbase equ $4f2 ; (L) -> OS header
-
- ;--- Magic numbers:
- bootmagic equ $1234 ; executable boot sector checksum
- DMAr equ $444d4172 ; DMAread()
-
-
- ;+
- ; Root Sector
- ;
- ; First branch (+0) goes to partition booter;
- ; Second branch (+2) goes to disk read routine.
- ; Bfat (+6) is a flag for size of FAT entries
- ;
- ;-
- _rootstart::
- base: bra.s rootboot ; boot some partition
- bra dmaread ; read sectors
-
-
- ;+
- ; rootboot - locate a bootable partition and boot from it
- ;
- ; - If the [ALT] key is down, just exit;
- ; - Search for bootable partition in sector image;
- ; - If none, just return;
- ; - Otherwise, load partition's boot sector into upper half
- ; of the 1K buffer, checksum it, and execute it if it
- ; checks out;
- ; - Adjust D7 on return so the DMA bus will not lock up.
- ;
- ;-
- rootboot: ; if this code fails, there's no C:
- bclr.b #2,_drvbits+3 ; so, clobber 'C' bit in _drvbits
- move.w #0,_bootdev ; initialise bootdev to be A:
- movem.l d3/d5,-(sp) ; save d3 and d5
- move.w #-1,-(sp) ; get state of the shift keys
- move.w #$0b,-(sp) ; d0 = Kbshift()
- trap #13
- addq.w #4,sp ; clean-up stack
- btst #3,d0 ; is [ALT] down?
- bne.s rb_r ; (yes, just return)
-
- moveq #3,d0 ; d0 = partition count
- moveq #$00f8,d1 ; d1 = mask for boot value
- lea base+$1c6(pc),a0 ; a0 -> first partition entry
- cmpi.l #DMAr,d3 ; does DMAread() exist?
- beq.s rb_0 ; if it does, d4 = physical unit number
- moveq #-1,d4 ; else d4 = -1 => no DMAread in ROM
- moveq #$80,d2 ; d2 = old boot value
- bra.s rb_1 ; and boot the old way
-
- rb_0: move.b d5,d2 ; else, is there a user preference?
- beq.s rb_5 ; if not, boot the first bootable partition
- rb_1: btst.b #0,(a0) ; does partition exist?
- beq.s rb_2 ; if not, try next partition slot
- and.b d1,(a0) ; mask off irrelevant bits
- cmp.b (a0),d2 ; p_flg matches boot value?
- beq.s rb_3 ; (yes --- boot the partition)
- rb_2: adda.w #12,a0 ; bump to next partition entry
- dbra d0,rb_1 ; (no --- look for other partitions)
- bra.s rb_r ; boot value search fails, return to ROMs
- ; boot the first bootable partition
- rb_5: btst.b #0,(a0) ; does partition exist?
- beq.s rb_6 ; if not, try next partition slot
- and.b d1,(a0) ; partition has a non-zero boot value?
- bne.s rb_3 ; (yes --- boot the partition)
- rb_6: adda.w #12,a0 ; (no --- bump to next partition entry)
- dbra d0,rb_5 ; look for other partitions
- ; if none is bootable, return to ROMs
-
- ;+
- ; Return to BIOS boot routine:
- ; - hack D7 so BIOS never does any more reads
- ; (so the DMA bus will not lock up).
- ;
- ; Modified 18-Feb-1988 by AKP to hack D7 (and stop looking on the DMA bus)
- ; ONLY on 11/20-derived ROMs. Newer ROMs have this bug fixed.
- ;-
- rb_r: addq.w #$08,sp ; clean up stack
- rb_bs: move.l _sysbase,a0 ; get the system header address
- move.l $18(a0),d0 ; d0.l = MMDDYYYY of ROM date
- swap d0 ; d0.l = YYYYMMDD of ROM date
- cmp.l #$19870422,d0 ; does this version of ROM need bootstop?
- bcc.s dontstop ; nope, if OS is built on or after 4/22/87
- move.w #$100-$20,d7 ; prevent any other boot sector loads
- dontstop:
- rts ; no bootable partitions
-
-
- ;+
- ; Handle bootable partition:
- ; - read its boot sector;
- ; - checksum it;
- ; - if it is executable, call it.
- ;-
- rb_3: move.l 4(a0),d6 ; d6 = sector number
- moveq #1,d5 ; d5 = sector count = 1
- lea base+$200(pc),a4 ; a4 -> upper half of 1K buffer
- bsr.s dmaread ; read partition's boot sector
- tst.w d0 ; successful?
- bne.s rb_r ; (punt on failure)
-
- move.l a4,a0 ; a0 -> buffer to checksum
- move.w #$0ff,d1 ; checksum $100 words
- moveq #0,d0 ; initialise checksum = 0
- rb_4: add.w (a0)+,d0 ; add (next) word
- dbra d1,rb_4 ; (loop for every word)
- cmp.w #bootmagic,d0 ; is the sector executable?
- bne.s rb_r ; (no --- return to OS)
- lea dmaread(pc),a3 ; a3 -> disk read routine
- lea rb_bs(pc),a5 ; a5 -> bootstop code
- movem.l (sp)+,d3/d5 ; restore d3 and d5
- jmp (a4) ; yes --- jump there
-
-
- ;+
- ; dmaread - read sectors from hard disk
- ; Passed: d4.w = physical unit number (if DMAread() is in ROM)
- ; or -1 (if DMAread() is not in ROM)
- ; d5.w = sector count
- ; d6.l = sector number
- ; d7.b = ddd00000 ('ddd' is the ACSI device number, 0..7)
- ; a4.l -> buffer address
- ;
- ; Returns: EQ: success
- ; NE: read failed;
- ;
- ; Uses: a5-a6/d0-d1 for dmaread here
- ; a0-a2/d0-d2 for DMAread in ROM
- ;-
- dmaread:
- tst.w d4 ; DMAread exists in ROM?
- bmi.s dmr_0 ; if not, use dmaread() in this root sector
- move.w d4,-(sp) ; pdev
- move.l a4,-(sp) ; buf
- move.w d5,-(sp) ; count
- move.l d6,-(sp) ; sectnum
- move.w #$2a,-(sp) ; DMAread(sectnum, count, buf, pdev)
- trap #14
- adda.w #$0e,sp ; clean up stack
- bra ww_w ; done
-
- dmr_0: st flock ; lock DMA chip (against vblank)
- move.l _hz_200,d0 ; delay for 1/200th..1/100th of a second
- addq.l #2,d0 ; d0 = target time
- dmr_dl: cmp.l _hz_200,d0 ; target time passed?
- bcc.s dmr_dl ; (not yet)
-
- move.w #dmahigh,a6 ; a6 -> base of DMA address registers
- movem.l d6/a4,-(sp) ; stuff sect# & addr onto stack for access
- move.b 7(sp),4(a6) ; load dmalow, (do not change the order)
- move.b 6(sp),2(a6) ; dmamid, (of loading these.)
- move.b 5(sp),(a6) ; and dmahigh.
-
- lea dmr_st(pc),a6 ; a6 -> command frame table
- move.b 1(sp),1(a6) ; write high,
- move.b 2(sp),5(a6) ; mid,
- move.b 3(sp),9(a6) ; and low sector bytes in table
- move.b d5,$d(a6) ; write sector count in table
- addq.w #$8,sp ; (cleanup stack)
-
- move.w #fifo,a6 ; a6 -> DMA control register
- move.w #diskctl,a5 ; a5 -> DMA data register
-
- move.w #$198,(a6) ; toggle R/W, leave in Read state
- move.w #$098,(a6)
- move.w d5,(a5) ; write sector count register
-
- move.w #$088,(a6) ; select dma bus (not SCR)
-
- moveq #0,d0 ; clear d0
- move.b d7,d0 ; setup d0.L with devno+command
- or.b #$08,d0 ; d0.b = devno<<5 .OR. "READ" command bits
- swap d0
- move.w #$08a,d0
- bsr.s wcbyte ; d0.L = xxxxxxxxDDD01000xxxxxxx010001010
-
- lea dmr_st(pc),a0 ; a0 -> bytestream for commands
- moveq #3,d2
- dmr_1: move.l (a0)+,d0 ; get next command byte
- bsr.s wcbyte ; write it
- dbra d2,dmr_1
-
- move.l #$0000000a,(a5) ; write byte 5 (controlByte = $00)
- move.l #400,d1 ; timeout = 2.0 sec
- bsr.s wwait ; wait for completion
-
- move.w #$08a,(a6) ; select status reg
- move.w (a5),d0 ; get return code from DMA device
- and.w #$00ff,d0 ; strip crufty bits
- beq.s dmr_r ; (return if OK)
-
- ;--- reset DMA, return status
- dmr_q: moveq #-1,d0 ; return -1 (error)
- dmr_r: move.w #$080,(a6) ; cleanup DMA chip for floppy driver
- sf flock ; unlock DMA chip
- ww_w: rts ; return
-
-
- ;--- bytes in the command packet:
- dmr_st: dc.l $0000008a ; byte 1 (devno = 0, blockno = 0)
- dc.l $0000008a ; byte 2 (blockno = 0)
- dc.l $0000008a ; byte 3 (blockno = 0)
- dc.l $0001008a ; byte 4 (count = 1)
-
-
- ;+
- ; wcbyte - write ACSI command byte, wait for IRQ
- ; Passed: D0.L = command byte and FIFO control
- ; bits 16..23 = command byte,
- ; bits 0..7 = FIFO control bits
- ; a5 -> $ff8604
- ;
- ; Returns: NE on failure (timeout) to the CALLER'S CALLER
- ; EQ on successful ACK
- ;
- ; Uses: d1
- ;
- ;-
- wcbyte: move.l d0,(a5) ; write WDC, WDL [due to jwt]
- moveq #10,d1 ; wait 1/20th second
- wwait: add.l _hz_200,d1 ; d1 = time to quit at...
- ww_1: btst.b #5,gpip ; disk done?
- beq.s ww_w ; (yes, return)
- cmp.l _hz_200,d1 ; timeout?
- bcc.s ww_1 ; (not yet -- wait some more...)
- addq.w #4,sp ; pop the return address
- bra.s dmr_q ; handle error
-
- _rootend::
-
- bss
- ;+
- ; Hard disk partition information
- ;
- ;-
- format_info: ds.b 12 ; formatting information
- hd_size: ds.l 1 ; hd_siz
- part0: ds.b 12 ; partition 0
- part1: ds.b 12 ; partition 1
- part2: ds.b 12 ; partition 2
- part3: ds.b 12 ; partition 3
- bsl_st: ds.l 1 ; bad sector list start
- bsl_cnt: ds.l 1 ; bad sector list count
- checksum: ds.w 1 ; (reserved for sector chksum)
-
-